/*
 * s_auto_plant_para.c
 *
 *  Created on: Sep 11, 2020
 *      Author: hemingway
 */
#include "s_auto_plant_para.h"

#include <stdio.h>
#include <string.h>

#include "s_nor_flash.h"
#include "s_lock_buzzer.h"
#include "h_cc2640r2f_adc.h"

#define S_AUTO_PLANT_SINGLE_MAX_TIME				30 //s
#define S_AUTO_PLANT_DEFAULT_WATER_TIME				46800 //1*3600 + 9 * 60 + 20 //46800 //utc+8: 21:00:00
// #define S_AUTO_PLANT_DEFAULT_WATER_TIME_1			

#define S_AUTO_PLANT_DEFAULT_MOTOR_VALUE			80
	
#define S_AUTO_PLANT_US_COMPLEMENT_VALUE			((unsigned int) ~0)

#define S_AUTO_PLANT_DEFAULT_LOW_POWER_THREAD		853700
#define S_AUTO_PLANT_DEFAULT_MAX_CHECK_TIMES		3

#define S_AUTO_PLANT_DEFAULT_NEXT_CHECK_SECONDS		10 //120 //300 //s -> 5min

#define S_AUTO_PLANT_DEFAULT_ACD_VALUE				1420000

s_auto_plant_para_t s_auto_plant_para;

signed char S_Auto_Plant_Para_Check(s_auto_plant_para_t *plant_para)
{
	// S_Auto_Plant_Para_Show(plant_para);
	if(plant_para->single_water_time[0] + plant_para->single_water_time_complement[0] != S_AUTO_PLANT_US_COMPLEMENT_VALUE)
	{
		// printf("not comlpement\n");
		return (-1);
	}
	if(plant_para->running_mode != s_auto_plant_para_running_spec_water_time_only && \
		plant_para->running_mode != s_auto_plant_para_running_with_adc_value)
	{
		// printf("mode failed\r\n");
		return (-2);
	}

	return 0;
}

signed char S_Auto_Plant_Para_Set_Single_Water_Time_Uint_Seconds(s_auto_plant_para_t *plant_para, unsigned char index, unsigned int sec)
{
	if(NULL == plant_para)
	{
		return (-1);
	}
	if(index > 2)
    {
        return (-2);
    }
	plant_para->single_water_time[index] = sec;
	plant_para->single_water_time_complement[index] = ~(sec);
	return 0;
}

unsigned int S_Auto_Plant_Para_Get_Single_Water_Time_Uint_Seconds(s_auto_plant_para_t *plant_para, unsigned char index)
{
	if(NULL == plant_para)
	{
		return 0;
	}
	if(index > 2)
    {
        return 0;
    }
	return plant_para->single_water_time[index];
}



signed char S_Auto_Plant_Para_Set_Running_Mode(s_auto_plant_para_t *plant_para, s_auto_plant_para_running_mode mode)
{
	if(NULL == plant_para)
	{
		return (-1);
	}
	plant_para->running_mode = mode;
	return 0;
}

s_auto_plant_para_running_mode S_Auto_Plant_Para_Get_Running_Mode(s_auto_plant_para_t *plant_para)
{
	if(NULL == plant_para)
	{
		return s_auto_plant_para_running_notRight;
	}
	return plant_para->running_mode;
}

static void s_auto_plant_para_order_water_day_time_less_2_big(s_auto_plant_para_t *plant_para)
{
	unsigned char i, j, enable_nums = 0U, disable_nums = 0U;
	unsigned int enable_times[3], temp;
	unsigned int disable_times[3];

	for(i = 0U; i < 3; i++)
	{
		if(S_Auto_Plant_Para_Get_Water_Day_Time_Enable(plant_para, i))
		{
			enable_times[enable_nums++] = S_Auto_Plant_Para_Get_Water_Day_Time_Value(plant_para, i);
		}
		else
		{
			disable_times[disable_nums++] = S_Auto_Plant_Para_Get_Water_Day_Time_Value(plant_para, i);
		}
	}

	printf("the enable_nums is %d\r\n", enable_nums);

	for(i = 0U; i < enable_nums; i++)
	{
		printf("the enable times %d\r\n", enable_times[i]);
	}

	// order enable times
	for(i = 0U; i < enable_nums; i++)
	{
		for(j = 0U; j < enable_nums - i - 1; j++)
		{
			if(enable_times[j] > enable_times[j + 1])
			{
				temp = enable_times[j + 1];
				enable_times[j + 1] = enable_times[j];
				enable_times[j] = temp;
			}
		}
	}
	// put enable times back
	for(i = 0U; i < enable_nums; i++)
	{
		plant_para->water_day_times.water_day_time_enable[i] = 1;
		plant_para->water_day_times.water_day_time[i] = enable_times[i];
	}

	// just put the disable back
	for(i = 0; i < disable_nums; i ++)
	{
		plant_para->water_day_times.water_day_time_enable[i + enable_nums] = 0;
		plant_para->water_day_times.water_day_time[i + enable_nums] = disable_times[i];
	}


	printf("the day times is %d(%d), %d(%d), %d(%d)\n", \
		plant_para->water_day_times.water_day_time[0], plant_para->water_day_times.water_day_time_enable[0], \
		plant_para->water_day_times.water_day_time[1], plant_para->water_day_times.water_day_time_enable[1], \
		plant_para->water_day_times.water_day_time[2], plant_para->water_day_times.water_day_time_enable[2]);	
}

signed char S_Auto_Plant_Para_Set_Water_Day_Time(s_auto_plant_para_t *plant_para, unsigned char index, unsigned int value)
{
	if(NULL == plant_para)
	{
		return (-1);
	}

	if(index > 3)
	{
		return (-2);
	}

	plant_para->water_day_times.water_day_time_enable[index] = 1;
	plant_para->water_day_times.water_day_time[index] = value;

	s_auto_plant_para_order_water_day_time_less_2_big(plant_para);
	return 0;
}

unsigned char S_Auto_Plant_Para_Get_Water_Day_Time_Enable(s_auto_plant_para_t *plant_para, unsigned char index)
{
	if(NULL == plant_para)
	{
		return 0;
	}
	if(index > 3)
	{
		return 0;
	}
	return plant_para->water_day_times.water_day_time_enable[index];
}

unsigned int S_Auto_Plant_Para_Get_Water_Day_Time_Value(s_auto_plant_para_t *plant_para, unsigned char index)
{
	if(NULL == plant_para)
	{
		return 0;
	}
	if(index > 3)
	{
		return 0;
	}
	return plant_para->water_day_times.water_day_time[index];
}

signed char S_Auto_Plant_Para_Disable_Water_Day_Time(s_auto_plant_para_t *plant_para, unsigned char index)
{
	if(NULL == plant_para)
	{
		return (-1);
	}

	if(index > 3)
	{
		return (-2);
	}

	plant_para->water_day_times.water_day_time_enable[index] = 0;

	s_auto_plant_para_order_water_day_time_less_2_big(plant_para);

	return 0;
}

signed char S_Auto_Plant_Para_Set_Motor_Value(s_auto_plant_para_t *plant_para, unsigned char index, unsigned int value)
{
	if(NULL == plant_para)
	{
		return (-1);
	}
	if(index > 2)
	{
		return (-2);
	}
	plant_para->plant_motor_value[index] = value;
	return 0;
}

unsigned int S_Auto_Plant_Para_Get_Motor_Value(s_auto_plant_para_t *plant_para, unsigned char index)
{
	if(NULL == plant_para)
	{
		return 0;
	}
	if(index > 2)
	{
		return 0;
	}
	return plant_para->plant_motor_value[index];
}

signed char S_Auto_Plant_Para_Set_ADC_Value(s_auto_plant_para_t *plant_para, unsigned char index, unsigned int value)
{
	if(NULL == plant_para)
	{
		return (-1);
	}
	if(index > 2)
	{
		return (-2);
	}
	plant_para->plant_adc_value[index] = value;
	return 0;
}

unsigned int S_Auto_Plant_Para_Get_ADC_Value(s_auto_plant_para_t *plant_para, unsigned char index)
{
	if(NULL == plant_para)
	{
		return 0;
	}
	if(index > 2)
	{
		return 0;
	}
	return plant_para->plant_adc_value[index];
}

signed char S_Auto_Plant_Para_Set_LowPower_Value(s_auto_plant_para_t *plant_para, unsigned int value)
{
	if(NULL == plant_para)
	{
		return (-1);
	}
	plant_para->plant_low_power_thread = value;
	return 0;
}

unsigned int S_Auto_Plant_Para_Get_LowPower_Value(s_auto_plant_para_t *plant_para)
{
	if(NULL == plant_para)
	{
		return (1);
	}
	return plant_para->plant_low_power_thread;
}

signed char S_Auto_Plant_Para_Set_MAX_CheckTimes(s_auto_plant_para_t *plant_para, unsigned int value)
{
	if(NULL == plant_para)
	{
		return (-1);
	}
	plant_para->plant_water_max_check_times = value;
	return 0;
}

unsigned int S_Auto_Plant_Para_Get_MAX_CheckTimes(s_auto_plant_para_t *plant_para)
{
	if(NULL == plant_para)
	{
		return (1);
	}
	return plant_para->plant_water_max_check_times;
}

signed char S_Auto_Plant_Para_Set_Next_CheckSeconds(s_auto_plant_para_t *plant_para, unsigned int value)
{
	if(NULL == plant_para)
	{
		return (-1);
	}
	plant_para->plant_water_next_check_seconds = value;
	return 0;
}

unsigned int S_Auto_Plant_Para_Get_Next_CheckSeconds(s_auto_plant_para_t *plant_para)
{
	if(NULL == plant_para)
	{
		return (1);
	}
	return plant_para->plant_water_next_check_seconds;
}

signed char S_Auto_Plant_Para_Init(s_auto_plant_para_t *plant_para)
{
//	unsigned int bat = 0U;
	S_Auto_Plant_Para_Update_From_Flash(plant_para);
	if(S_Auto_Plant_Para_Check(plant_para))
	{
		S_Auto_Plant_Para_Reset(plant_para);
		S_Auto_Plant_Para_Restore_To_Flash(plant_para);
		// Check bat
		if(0 == S_Auto_Plant_Battery_Check(plant_para))
		{
			S_Lock_Buzzer_Success_2();
		}
		return 1;
	}
	else
	{
		// S_Auto_Plant_Para_Reset(plant_para);
		// S_Auto_Plant_Para_Restore_To_Flash(plant_para);
		// Check bat
		if(0 == S_Auto_Plant_Battery_Check(plant_para))
		{
			S_Lock_Buzzer_Success();
		}
		
		return 0;
	}
}

signed char S_Auto_Plant_Battery_Check(s_auto_plant_para_t *plant_para)
{
	unsigned int adc = H_CC2640R2F_ADC_Read_MicroVolts_byNum(0);
	if(adc < S_Auto_Plant_Para_Get_LowPower_Value(plant_para))
	{
		S_Lock_Buzzer_LowPower();
		return 1;
	}
	else
	{
		return 0;
	}
}

signed char S_Auto_Plant_Para_Reset(s_auto_plant_para_t *plant_para)
{
	S_Auto_Plant_Para_Set_Running_Mode(plant_para, s_auto_plant_para_running_spec_water_time_only);
	S_Auto_Plant_Para_Set_Single_Water_Time_Uint_Seconds(plant_para, 0, S_AUTO_PLANT_SINGLE_MAX_TIME);
	S_Auto_Plant_Para_Set_Single_Water_Time_Uint_Seconds(plant_para, 1, S_AUTO_PLANT_SINGLE_MAX_TIME);
	// S_Auto_Plant_Para_Set_Water_Day_Time(plant_para, 0, S_AUTO_PLANT_DEFAULT_WATER_TIME);
	// S_Auto_Plant_Para_Disable_Water_Day_Time(plant_para, 1);
	// S_Auto_Plant_Para_Disable_Water_Day_Time(plant_para, 2);
	plant_para->water_day_times.water_day_time_enable[0] = 1;
	plant_para->water_day_times.water_day_time[0] = S_AUTO_PLANT_DEFAULT_WATER_TIME;
	plant_para->water_day_times.water_day_time_enable[1] = 0U;
	plant_para->water_day_times.water_day_time[1] = 0;
	plant_para->water_day_times.water_day_time_enable[2] = 0U;
	plant_para->water_day_times.water_day_time[2] = 0U;
	
	S_Auto_Plant_Para_Set_Motor_Value(plant_para, 0, S_AUTO_PLANT_DEFAULT_MOTOR_VALUE);
	S_Auto_Plant_Para_Set_Motor_Value(plant_para, 1, S_AUTO_PLANT_DEFAULT_MOTOR_VALUE);

	S_Auto_Plant_Para_Set_LowPower_Value(plant_para, S_AUTO_PLANT_DEFAULT_LOW_POWER_THREAD);
	S_Auto_Plant_Para_Set_MAX_CheckTimes(plant_para, S_AUTO_PLANT_DEFAULT_MAX_CHECK_TIMES);

	S_Auto_Plant_Para_Set_Next_CheckSeconds(plant_para, S_AUTO_PLANT_DEFAULT_NEXT_CHECK_SECONDS);

	S_Auto_Plant_Para_Set_ADC_Value(plant_para, 0, S_AUTO_PLANT_DEFAULT_ACD_VALUE);
	S_Auto_Plant_Para_Set_ADC_Value(plant_para, 1, S_AUTO_PLANT_DEFAULT_ACD_VALUE);

    return 0;
}

signed char S_Auto_Plant_Para_Restore_To_Flash(s_auto_plant_para_t *plant_para)
{
	if(NULL == plant_para)
	{
		return (-1);
	}

	return S_Nor_Flash_Write_Para_Struct((unsigned char *)plant_para, sizeof(s_auto_plant_para_t));
}


signed char S_Auto_Plant_Para_Update_From_Flash(s_auto_plant_para_t *plant_para)
{
	if(NULL == plant_para)
	{
		return (-1);
	}

//	unsigned char data[5];

	return S_Nor_Flash_Read_Para_Struct((unsigned char *)plant_para, sizeof(s_auto_plant_para_t));
}



void S_Auto_Plant_Para_Show(s_auto_plant_para_t *plant_para)
{
	if(NULL == plant_para)
	{
		return;
	}
	printf("the running_mode is %d\r\n", plant_para->running_mode);
	printf("the single_water_time is %d, %d\r\n", plant_para->single_water_time, plant_para->single_water_time_complement);
	printf("the adc is %d, %d\n", plant_para->plant_adc_value[0], plant_para->plant_adc_value[1]);
	printf("the day times is %d(%d), %d(%d), %d(%d)\n", \
		plant_para->water_day_times.water_day_time[0], plant_para->water_day_times.water_day_time_enable[0], \
		plant_para->water_day_times.water_day_time[1], plant_para->water_day_times.water_day_time_enable[1], \
		plant_para->water_day_times.water_day_time[2], plant_para->water_day_times.water_day_time_enable[2]);	
	printf("the motor is %d, %d\n", plant_para->plant_motor_value[0], plant_para->plant_motor_value[1]);
}

signed char S_Auto_Plant_Para_Test(void)
{
	s_auto_plant_para_t n;
	S_Auto_Plant_Para_Show(&s_auto_plant_para);
	S_Auto_Plant_Para_Restore_To_Flash(&s_auto_plant_para);

	S_Auto_Plant_Para_Set_Motor_Value(&n, 0, 100);
	S_Auto_Plant_Para_Show(&n);
	S_Auto_Plant_Para_Update_From_Flash(&n);
	S_Auto_Plant_Para_Show(&n);

	return 0;
}

